package cc.rengu.igas.bsps.core.service.base;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.BspsTreeNodeConstant;
import cc.rengu.igas.bsps.common.dao.BspsMchntBindInfoMapper;
import cc.rengu.igas.bsps.common.dao.BspsUserInfoMapper;
import cc.rengu.igas.bsps.common.dao.impl.BspsMchntBindInfoMapperImpl;
import cc.rengu.igas.bsps.common.dao.impl.BspsUserInfoMapperImpl;
import cc.rengu.igas.bsps.common.entity.MchntBindInfo;
import cc.rengu.igas.bsps.common.entity.UserInfo;
import cc.rengu.igas.bsps.common.enums.BspsUserRoleTypeEnum;
import cc.rengu.igas.bsps.common.enums.MchntTypeEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.share.common.constant.ShareTreeNodeConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.CouponDetailBean;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.OrderDetail;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.PublicService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.share.core.realize.impl.PublicServiceImpl;
import cc.rengu.igas.share.core.realize.impl.RiskMonitorServiceImpl;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderDetailMapper;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderDetailMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.*;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.*;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.RiskMonitorService;
import cc.rengu.oltp.service.realize.SafeKeyBoardService;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.service.realize.impl.SafeKeyBoardServiceImpl;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.annotation.BIZ_AFTER;
import cc.rengu.oltp.utility.annotation.BIZ_BEFORE;
import cc.rengu.oltp.utility.annotation.BIZ_PROCESS;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 支付退货服务基类
 * Created by 王成 on 2018/4/17.
 */
public abstract class RefundService extends BizBaseService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID);
        String msgSrcId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MSG_SRC_ID);
        String chnlId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.CHANNEL_ID);
        String bizType = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE);
        String transAmt = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.ORDER_AMT);
        /*默认部分退款*/
        xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.REFUND_TYPE, AppParamConstant.NO);
        /*原交易参与营销标识*/
        boolean isOrderMomp = false;
        xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.ORDER_JOIN_MOMP, AppParamConstant.NO);
        /*订单是否全部退款*/
        boolean isOrderAllRefund = false;
        xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.ORDER_ALL_REFUND_FLAG, AppParamConstant.NO);
        /* Step1：查找BIZ_BEFORE的注解*/
        invokeBizAnnoMethod(BIZ_BEFORE.class);

        /* Step2：检查验签状态 */
        String verifySignFlag = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG);
        if (AppParamConstant.NO.equals(verifySignFlag)) {
            throw new BizException(RespCodeEnum.VERIFY_SIGN_ERROR.getRespCode(), RespCodeEnum.VERIFY_SIGN_ERROR.getRespDesc());
        }

        /* Step3：检查接口合法性 */
        PublicService publicService = new PublicServiceImpl();
        publicService.checkInputValidity(msgSrcId, "P04BS001");

        /* Step4：检查商户合法性 */
        /* 商户号 */
        String mchntNo = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MCHNT_NO);
        rglog.info("检查商户状态");
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(instId, mchntNo);
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", mchntNo);
            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
        }
        /*校验产品权限*/
        boolean checkResult = mchntService.checkMchntAuth(instId, mchntNo, null, txnNum, bizType, AcctTypeEnum.ALL.getAcctType());
        if (!checkResult) {
            rglog.error("商户<{}>无此交易<{}>权限!", mchntNo, txnNum);
            throw new BizException(RespCodeEnum.MCHNT_NO_PERMISSION.getRespCode(), RespCodeEnum.MCHNT_NO_PERMISSION.getRespDesc());
        }

        /*系统流水号*/
        String origSysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.ORIG_SYS_SEQ_NUM);
        String userId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.USER_ID);
        //查询用户
        BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
        UserInfo userInfo = bspsUserInfoMapper.selectBspsUserInfoByUserId(instId, userId);
        if (userInfo == null) {
            rglog.error("用户不存在");
            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
        }
        /*根据商户号、系统流水号查询原支付交易*/
        OrderService orderService = new OrderServiceImpl();
        OrderInfo orderInfo = orderService.selectOrderInfoBySysSeqNum(instId, origSysSeqNum);
        List<MchntOrderInfo> mchntOrderInfos = orderInfo.getMchntOrderInfoList();
        if (null == mchntOrderInfos || mchntOrderInfos.isEmpty()) {
            rglog.error("商户订单不存在");
            throw new BizException(RespCodeEnum.GET_MCHNT_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_ORDER_INFO_ERROR.getRespDesc());
        }
        Optional<MchntOrderInfo> first = mchntOrderInfos.stream().filter(item -> item.getMchntNo().equals(mchntNo)).findFirst();
        if (!first.isPresent()) {
            rglog.info("根据机构号<{}>、流水号<{}>、商户号<{}>查无商户订单", instId, origSysSeqNum, mchntNo);
            throw new BizException(RespCodeEnum.GET_PAY_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_PAY_ORDER_INFO_ERROR.getRespDesc());
        }
        MchntOrderInfo mchntOrderInfo = first.get();
        /*校验用户权限step1 获取用户绑定关系bean*/
        BspsMchntBindInfoMapper bspsMchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
        MchntBindInfo mchntBindInfo = bspsMchntBindInfoMapper.selectBspsMchntBindInfoListByUserIdAndMchntNo(instId, userId, mchntNo);
        /*校验用户权限step2 用户与商户绑定关系不能为空,商户是连锁商户门店时，查询用户是否为连锁商户用户*/
        if ((mchntBindInfo == null) && (MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntInfo.getMchntType()))) {
            mchntBindInfo = bspsMchntBindInfoMapper.selectBspsMchntBindInfoListByUserIdAndMchntNo(instId, userId, mchntInfo.getChainMchntNo());
        }
        if (mchntBindInfo == null) {
            rglog.error("用户与商户绑定关系不能为空");
            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
        }
        /*校验用户权限step3 校验用户权限-法人、店长都有权限,白名单的收银员有权限*/
        if (!((BspsUserRoleTypeEnum.MCHNT_ARTIF.getRoleType().equals(mchntBindInfo.getBindUserRole()))
                || (BspsUserRoleTypeEnum.MCHNT_MANAGER.getRoleType().equals(mchntBindInfo.getBindUserRole())))) {
            rglog.info("非法人、店长进行退款交易");
            //校验白名单收银员退款权限,null/NO为无权限
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam sysParam = sysParamService.getSysParamInfo(instId, BspsAppParamConstant.BSPS_REFUND_MERCH, mchntNo);
            if (sysParam == null) {
                rglog.error("无权限角色退款-非白名单");
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }
            if (AppParamConstant.YES.equals(sysParam.getParamValue())) {
                rglog.info("非法人、店长-角色权限校验通过");
                /*检查用户订单权限*/
                if (!userId.equals(mchntOrderInfo.getUserId())) {
                    rglog.error("无权限用户退款-用户关联订单用户校验失败");
                    throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
                }
                rglog.info("非法人、店长-用户权限校验通过");
            } else {
                rglog.error("无权限角色退款");
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }
        }
        //校验密码信息
        SafeKeyBoardService safeKeyBoardService = new SafeKeyBoardServiceImpl();
        String chanlId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_CHANNEL_ID);
        String transPassword = xmlTreeUtil.getXmlTreeStringValue("transPassword");
        if (chanlId.equals("PCWEB")) {
            String session = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_SESSION);
            UserSessionInfo keySessionInfo = JSON.parseObject(RedisUtil.onceGet(session), UserSessionInfo.class);
            String randomString = keySessionInfo.getRandomString();
            keySessionInfo.setRandomString("");
            RedisUtil.onceSet(session, JSONObject.toJSONString(keySessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);

            PasswordInfo passwordInfo = new PasswordInfo(mchntNo, PinTypeEnum.MIXED, transPassword);
            transPassword = safeKeyBoardService.encryptPassword(instId, "PCWEB", passwordInfo, null);
            if (!transPassword.equals(userInfo.getTransPassword())) {
                rglog.error("交易密码校验失败！拒绝退款请求！userId:<{}>", userId);
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }

        } else {
            /* 校验交易密码 */
            PasswordInfo passwordInfo = new PasswordInfo(mchntNo, PinTypeEnum.DIGITAL, transPassword);
            transPassword = safeKeyBoardService.encryptPassword(instId, "H5", passwordInfo, null);
            if (!transPassword.equals(userInfo.getTransPassword())) {
                rglog.error("交易密码校验失败！拒绝退款请求！userId:<{}>", userId);
                throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
            }
        }

        rglog.error("========退款===========交易密码校验通过================================================");
        /*根据商户订单号查询原支付交易*/
        UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
        if (userOrderInfo == null) {
            rglog.info("用户订单不存在");
            throw new BizException(RespCodeEnum.GET_PAY_ORDER_INFO_ERROR.getRespCode(), RespCodeEnum.GET_PAY_ORDER_INFO_ERROR.getRespDesc());
        }
        /*判断订单是否支付成功*/
        if (!OrderStatusEnum.FINISH.getStatus().equals(userOrderInfo.getOrderStatus())) {
            rglog.error("订单状态<{}>,非成功<03>，不允许退款", userOrderInfo.getOrderStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }
        if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(userOrderInfo.getTransStatus())) {
            rglog.error("订单交易状态<{}>,非成功<1>，不允许退款", userOrderInfo.getTransStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }
        if (!BizStatusEnum.FINISH.getStatus().equals(userOrderInfo.getBizStatus()) &&
                !BizStatusEnum.PART_REFUND.getStatus().equals(userOrderInfo.getBizStatus()) &&
                !BizStatusEnum.CONFIRM.getStatus().equals(userOrderInfo.getBizStatus()) &&
                !BizStatusEnum.NOT_CONFIRM_PART_REFUND.getStatus().equals(userOrderInfo.getBizStatus())) {
            rglog.warn("业务状态<{}>,非完成<00>或部分退款<31>或未确认收货部分退货<33>或确认收货<50>，不允许退款", userOrderInfo.getBizStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }

        /*判断订单是否支付成功*/
        if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(mchntOrderInfo.getTransStatus())) {
            rglog.error("交易状态<{}>,非成功<1>，不允许退款", mchntOrderInfo.getTransStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }
        if (!BizStatusEnum.FINISH.getStatus().equals(mchntOrderInfo.getBizStatus()) &&
                !BizStatusEnum.PART_REFUND.getStatus().equals(mchntOrderInfo.getBizStatus()) &&
                !BizStatusEnum.CONFIRM.getStatus().equals(mchntOrderInfo.getBizStatus())) {
            rglog.error("业务状态<>非完成<00>或全额退款<30>，不允许退款", mchntOrderInfo.getBizStatus());
            throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
        }

        /*商户订单 退款金额检查*/
        String totalRefundAmt = "0.00";
        if (mchntOrderInfo.getRefundAmt() != null) {
            totalRefundAmt = mchntOrderInfo.getRefundAmt();
        }
        try {
            transAmt = AmountUtil.checkAmt(transAmt, 2, false, false);
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.ORDER_AMT, transAmt);
        } catch (Exception e) {
            rglog.debug("退款金额<{}>非法", transAmt);
            throw new BizException(RespCodeEnum.AMOUNT_IS_UN_NORMAL.getRespCode(), RespCodeEnum.AMOUNT_IS_UN_NORMAL.getRespDesc());
        }
        totalRefundAmt = AmountUtil.addition(transAmt, totalRefundAmt);
        rglog.debug("本次退款金额<{}>,商户订单已退款金额<{}>,商户订单金额<{}>", transAmt, totalRefundAmt, mchntOrderInfo.getOrderAmt());
        if (AmountUtil.compare(mchntOrderInfo.getOrderAmt(), totalRefundAmt) == -1) {
            /*累计退款金额超限*/
            rglog.error("本次退款金额<{}>,已退款金额<{}>,订单金额<{}>.累计退款金额超限", transAmt, totalRefundAmt, mchntOrderInfo.getOrderAmt());
            throw new BizException(RespCodeEnum.REFUND_AMT_OVER_LIMIT.getRespCode(), RespCodeEnum.REFUND_AMT_OVER_LIMIT.getRespDesc());
        }

        //用户订单退款金额检查
        String userTotalRefundAmt = "0.00";
        for (MchntOrderInfo mchntOrderInfo1 : mchntOrderInfos) {
            userTotalRefundAmt = AmountUtil.addition(userTotalRefundAmt, mchntOrderInfo1.getRefundAmt());
        }
        /*是否全订单退款*/
        rglog.debug("本次退款金额:<{}>,当前订单累计退款金额:<{}>,用户订单金额:<{}>", transAmt, userTotalRefundAmt, userOrderInfo.getOrderAmt());
        userTotalRefundAmt = AmountUtil.addition(userTotalRefundAmt, transAmt);
        if (AmountUtil.compare(userTotalRefundAmt, userOrderInfo.getOrderAmt()) == 1) {
            rglog.error("用户累计退款金额:<{}>大于用户订单金额:<{}>", userTotalRefundAmt, userOrderInfo.getOrderAmt());
            throw new BizException(RespCodeEnum.REFUND_AMT_OVER_LIMIT.getRespCode(), RespCodeEnum.REFUND_AMT_OVER_LIMIT.getRespDesc());
        } else if (AmountUtil.compare(transAmt, userOrderInfo.getOrderAmt()) == 0) {
            rglog.debug("本地退款金额:<{}>等于用户订单金额:<{}>，全订单退款", transAmt, userOrderInfo.getOrderAmt());
            isOrderAllRefund = true;
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.ORDER_ALL_REFUND_FLAG, AppParamConstant.YES);
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.REFUND_TYPE, AppParamConstant.YES);
        } else if (AmountUtil.compare(userTotalRefundAmt, userOrderInfo.getOrderAmt()) == 0) {
            rglog.debug("累计退款金额:<{}>等于用户订单金额:<{}>，用户订单全订单退款", userTotalRefundAmt, userOrderInfo.getOrderAmt());
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.REFUND_TYPE, AppParamConstant.YES);
        }

        /*是否参与营销*/
        rglog.debug("商户对客营销金额:<{}>,商户手续费优惠金额:<{}>", mchntOrderInfo.getCustomerMarketAmt(), mchntOrderInfo.getMchntDiscountFee());
        if (0 != AmountUtil.compare("0", mchntOrderInfo.getCustomerMarketAmt())) {
            isOrderMomp = true;
            xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.ORDER_JOIN_MOMP, AppParamConstant.YES);
        }

        /*根据原系统流水号查询商户退款订单，判断是否存在退款中的订单,如果存在退款中的拒绝当前退款*/
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> refundHistoryMchntOrderList = mchntOrderInfoMapper.selectMchntOrderInfoByOrigSysSeqNum(instId, mchntOrderInfo.getSysSeqNum());
        if (refundHistoryMchntOrderList != null && refundHistoryMchntOrderList.size() > 0) {
            Predicate<MchntOrderInfo> transStat = p -> TransStatusEnum.TRANS_TIMEOUT.getStatus().equals(p.getTransStatus());
            Predicate<MchntOrderInfo> bizStat = p -> BizStatusEnum.PROCESSING.getStatus().equals(p.getBizStatus());
            refundHistoryMchntOrderList = refundHistoryMchntOrderList.stream().filter(transStat.or(bizStat)).collect(Collectors.toList());
            if (refundHistoryMchntOrderList.size() > 0) {
                Predicate<MchntOrderInfo> mchnt = p -> mchntNo.equals(p.getMchntNo());
                Predicate<MchntOrderInfo> refundTxn = p -> "04".equals(p.getTxnNum().substring(1, 3));
                refundHistoryMchntOrderList = refundHistoryMchntOrderList.stream().filter(mchnt.and(refundTxn)).collect(Collectors.toList());
                if (refundHistoryMchntOrderList.size() > 0) {
                    rglog.error("原商户订单号<>、系统流水号<{}>存在退款状态<{}>未确定，不允许退款",
                            refundHistoryMchntOrderList.get(0).getMchntOrderId(), refundHistoryMchntOrderList.get(0).getSysSeqNum(), refundHistoryMchntOrderList.get(0).getBizStatus());
                    throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
                }
            }
        }

        //退款成功后累计商户订单的退款金额，此时累计会导致后期计算异常 因此注释
        // mchntOrderInfo.setRefundAmt(totalRefundAmt);
        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        List<PayOrderInfo> mompPayOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());
        if (!CollectionUtils.isEmpty(mompPayOrderInfoList)) {
            mompPayOrderInfoList = mompPayOrderInfoList.stream().filter(item -> "P01MO003".equals(item.getDstTxnNum())).sorted(Comparator.comparing(PayOrderInfo::getDstCallIndex)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(mompPayOrderInfoList)) {
                if (0 != AmountUtil.compare("0", mompPayOrderInfoList.get(0).getChannelDiscountAmt())) {
                    rglog.debug("营销订单有对客营销.<{}>", mompPayOrderInfoList.get(0).getChannelDiscountAmt());
                    isOrderMomp = true;
                    xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.ORDER_JOIN_MOMP, AppParamConstant.YES);
                }
            }
        }

        if (isOrderMomp) {
            if (!isOrderAllRefund) {
                rglog.error("订单参与了营销,不允许部分订单退款.");
                throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
            }
        }

        /* 将原交易信息设置到内部树 */
        GlobalTransUtil.setCacheValue(TransCacheConstant.ORIG_ORDER_INFO, orderInfo);

        /*实时清算订单不允许退款*/
        List<MchntOrderInfo> mchntOrderInfoListD0 = mchntOrderInfos.stream().filter(item -> AppParamConstant.YES.equals(item.getRealSettleFlag())).collect(Collectors.toList());
        if (mchntOrderInfoListD0.size() > 0) {
            mchntOrderInfoListD0 = mchntOrderInfoListD0.stream().filter(item -> item.getMchntNo().equals(mchntNo)).collect(Collectors.toList());
            if (mchntOrderInfoListD0.size() > 0) {
                rglog.info("商户订单信息表中存在实时入账订单,mchntNo:<{}>,sysSeqNum:<{}>.", mchntNo, userOrderInfo.getSysSeqNum());
                throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
            }
        }

        /*卡券购买类退款时上送*/
        CouponDetailBean couponDetailBean = new CouponDetailBean();
        List<OrderDetail> orderDetailList = new ArrayList<>();
        couponDetailBean.setRefundOrderDetailList(orderDetailList);
        MchntOrderDetailMapper mchntOrderDetailMapper = new MchntOrderDetailMapperImpl();
        for (MchntOrderInfo oriMchntOrderInfo : mchntOrderInfos) {
            if ("00".equals(oriMchntOrderInfo.getBizSceneType()) || "02".equals(oriMchntOrderInfo.getBizSceneType())) {
                List<MchntOrderDetail> mchntOrderDetailList = mchntOrderDetailMapper.selectMchntOrderDetailByMchntOrderId(oriMchntOrderInfo.getInstId(), oriMchntOrderInfo.getMchntNo(), oriMchntOrderInfo.getMchntOrderId());
                if (!CollectionUtils.isEmpty(mchntOrderDetailList)) {
                    for (MchntOrderDetail mchntOrderDetail : mchntOrderDetailList) {
                        OrderDetail orderDetail = new OrderDetail();
                        BeanUtil.beanCopy(mchntOrderDetail, orderDetail);
                        orderDetailList.add(orderDetail);
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(orderDetailList)) {
            if (!isOrderAllRefund) {
                rglog.debug("卡券购买类订单,必须全额退款.");
                throw new BizException(RespCodeEnum.ORDER_CANT_REFUND.getRespCode(), RespCodeEnum.ORDER_CANT_REFUND.getRespDesc());
            }
            ConvertUtil.convertInput(couponDetailBean);
        }

        //当期完成退款的金额
        xmlTreeUtil.setXmlTreeStringValue(ShareTreeNodeConstant.CURRENT_TOTAL_REFUND_AMT, totalRefundAmt);


        /* Step5：交易处理前客户化 */
        rglog.info("交易处理前客户化");

        return bizBeforeCust();
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {
        /* Step1：公共业务处理 */

        /* Step2：查找BIZ_PROCESS的注解 */
        invokeBizAnnoMethod(BIZ_PROCESS.class);

        /* Step3：业务逻辑处理*/
        return bizProcessCust(request);
    }

    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        /* Step1：业务调用后公共处理*/

        /* Step2：查找BIZ_AFTER的注解 */
        invokeBizAnnoMethod(BIZ_AFTER.class);

        /* Step3：业务调用后客户化处理 */
        bizAfterCust(response);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        RiskMonitorInfo riskMonitorInfo = new RiskMonitorInfo();
        RiskMonitorService riskMonitorService = new RiskMonitorServiceImpl();
        riskMonitorInfo.setTransMonitor(riskMonitorService);
        return riskMonitorInfo;
    }

    /**
     * 业务处理前客户化处理
     *
     * @return 业务处理实体类
     */
    protected abstract Object bizBeforeCust() throws Exception;

    /**
     * 业务逻辑处理客户化处理
     *
     * @param request 业务处理前的返回实体类
     * @return 业务处理结果
     */
    protected abstract BizResponse bizProcessCust(Object request) throws Exception;

    /**
     * 业务处理后逻辑处理
     *
     * @param response 业务调用响应信息
     */
    protected abstract void bizAfterCust(Object response) throws Exception;
}
